/*
 *  main.cpp
 *  XcodeGLUT
 *
 *  Created by Diego Andrade on 2/1/11.
 *  Copyright 2011 Carnegie Mellon University. All rights reserved.
 *
 */



#include <GLUT/glut.h>
//#include <GL/glut.h>
#include <fstream.h>
#include <iostream.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
using std::string;
#include <time.h>
//#include "TubeGeometry.h"
#define WINDOWS 0

#include "IOCOM.h"
#include "elec_solver.h"


using namespace std;


static char *RoutineName;
//TubeGeometry* tubeGeom;

float** MV; //coordinates array
float** CT; //centroid array
int npts=30;//22;

//Indices
int* A;
int* B;
int* C;

//------------------------------------------------------------------


elecslvr _elecslvr_obj;

float x =0.0;
float y =0.0;


//-------------------------------------------------------------------
struct point 
{
	float x;
	float y;   
};
//Structs can not be pass or inherited from classes

//----------------------------------------------------------------------
//Parser* parser;
static void usage()
{
	cout << "Usage is " << RoutineName << endl;
	cout << "\t[-x xrotation]" << endl;
	cout << "\t[-y yrotation]" << endl;
	cout << "\t[-z zrotation]" << endl;
	cout << "\t[-l] (laptop)" << endl;
	cout << "\t[-h] (this help message)" << endl;
}

static GLfloat   transxob, transyob, rotxob, rotyob, rotzob, zoomob;
static int 	 panLeft=0, panRight=1; // control panning for 3d effect
static GLboolean leftMouseDown=0;
static GLboolean middleMouseDown=0;
static GLboolean firstx=1,firsty=1;	// first MOUSEX (MOUSEY) reading?
static int	 oldx,oldy;		// previous value of MOUSEX and MOUSEY
static GLboolean ROTATEOB=0;		// rotate mesh?
static GLboolean PANOB=0; 		// rotate mesh back and forth for 3d effect?
static GLboolean WIRE=0;		// draw mesh in wireframe?
static GLboolean LAPTOP=0;              // display environment for laptop?
static GLboolean DATAPTS=0;
static GLboolean DATATGTS=0;
static GLboolean CURVEPTS=0;
static GLboolean CURVETGTS=0;
static GLboolean CIRCLES=0;
static GLboolean CIRCLENORMALS=0;
static GLboolean TUBE=0;
static GLboolean TORUS=0; //test to use alt modifier

/*-----------------------------------------------------------------------------*/




GLfloat brass_ambient[] = {0.33, 0.22, 0.03, 1.0}, 
brass_diffuse[] = {0.78,0.57, 0.11, 1.0}, 
brass_specular[] = {0.99, 0.91, 0.81, 1.0}, 
brass_shininess = 27.8;

/*-----------------------------------------------------------------------------*/

double tetra[4][3] = {{0,0,0},{1,0,0},
	{0,1,0},{0,0,1}};
int    win;  // window identifier 

// Point3d *   points;
// int*        faces[4];
// ColorArray* colorArray;

/******************************************************************************/
/******************************************************************************/

void gfxinit(void)
{
	//GLfloat ambient[] 	   = {0.0, 0.0, 0.0, 1.0};
	GLfloat ambient[] 	   = {0.5, 0.5, 0.5, 1.0};
	GLfloat diffuse[] 	   = {1.0, 1.0, 1.0, 1.0};
	//GLfloat position[]       = {0.0, 3.0, 3.0, 0.0};
	GLfloat position[]       = {1.0, 4.0, 4.0, 1.0};
	GLfloat lmodel_ambient[] = {0.2, 0.2, 0.2, 1.0};
	GLfloat local_view[] 	   = {0.0};
	
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
	glLightfv(GL_LIGHT0, GL_POSITION, position);
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
	glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
	
	glFrontFace(GL_CW);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_NORMALIZE);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);
	glClearColor (1.0, 1.0, 1.0, 1.0);
	glEnable (GL_POINT_SMOOTH);
	glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST); 
	glPointSize (3.0);
	
	transxob = transyob = 0.0;
	zoomob = 1.8;
}

/******************************************************************************/
/******************************************************************************/

void reshape(GLsizei w, GLsizei h)
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-20.0*(GLfloat)w/(GLfloat)h, 20.0*(GLfloat)w/(GLfloat)h, -20.0, 20.0, -1000.,1000.);
	//glOrtho(-8000.0, 8000.0, -8000.0, 8000.0, -10000.0,10000.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

/******************************************************************************/
/******************************************************************************/

void RotateOb (void)
{
	rotzob += 1.0; 
	if (rotzob > 360.0) rotzob -= 360.0;
	glutPostRedisplay();
}

/******************************************************************************/
/******************************************************************************/

void PanOb (void)
{
	if (panLeft)
	{
		rotzob += 1.0;
		if (rotzob > 360.0) rotzob -= 360.0;
		panLeft++;
		if (panLeft==30) { panLeft=0; panRight=1; }
	}
	else if (panRight)
	{
		rotzob -= 1.0;
		if (rotzob < 0.0) rotzob += 360.0;
		panRight++;
		if (panRight==30) { panRight=0; panLeft=1; }
	}
	glutPostRedisplay();
}

/******************************************************************************/
/******************************************************************************/

void visibility (int status)
{
	if (status != GLUT_VISIBLE) 
		glutIdleFunc (NULL);
	else if (ROTATEOB) glutIdleFunc (RotateOb);
	else if (PANOB)    glutIdleFunc (PanOb);
}

/******************************************************************************/
/******************************************************************************/

void mouse (int button, int state, int x, int y)
{
	switch (button) {
		case GLUT_LEFT_BUTTON:
			switch (state) {
				case GLUT_DOWN: 
					leftMouseDown = firstx = firsty = 1;
					glutSetCursor (GLUT_CURSOR_UP_DOWN); break;
				case GLUT_UP: 
					leftMouseDown = 0;
					glutSetCursor (GLUT_CURSOR_INHERIT); break;
				default: break;
			}
			break;
		case GLUT_MIDDLE_BUTTON:
			switch (state) {
				case GLUT_DOWN:
					middleMouseDown = firstx = firsty = 1; 
					glutSetCursor (GLUT_CURSOR_CYCLE); break;
				case GLUT_UP: 		
					middleMouseDown = 0; 
					glutSetCursor (GLUT_CURSOR_INHERIT); break;
				default: break;
			}
			break;
		default: break;
	}
}

/******************************************************************************/
/******************************************************************************/

void motionob (int x, int y)
{
	if (WINDOWS || LAPTOP)
    {
		if (!leftMouseDown && middleMouseDown)	   
		{
			if (firstx)  firstx=0; else zoomob -= (float).01*(x-oldx);
			if (zoomob < 0.0) zoomob = 0.0;
		}
		else if (leftMouseDown && middleMouseDown)
		{
			if (firstx)  firstx=0; else transxob += 10.0*(x-oldx); /* TRANSLATION: X */
			if (firsty)  firsty=0; else transyob += 10.0*(y-oldy); /* TRANSLATION: Y */
		}
		else if (leftMouseDown && !middleMouseDown) 
		{
			if (firstx)  firstx=0;
			else { rotyob += .5*(x-oldx); if (rotyob > 360.0) rotyob -= 360.0; } /* ORI: Y */
			
			if (firsty)  firsty=0;
			else { rotxob += .5*(y-oldy); if (rotxob > 360.0) rotxob -= 360.0; } /* ORI: X */
		}
    }
	else
    {
		if (leftMouseDown && !middleMouseDown)	   
		{
			if (firstx)  firstx=0; else zoomob -= (float).01*(x-oldx);
			if (zoomob < 0.0) zoomob = 0.0;
		}
		else if (leftMouseDown && middleMouseDown)
		{
			if (firstx)  firstx=0; else transxob += 10.0*(x-oldx); /* TRANSLATION: X */
			if (firsty)  firsty=0; else transyob += 10.0*(y-oldy); /* TRANSLATION: Y */
		}
		else if (middleMouseDown) 
		{
			if (firstx)  firstx=0;
			else { rotyob += .5*(x-oldx); if (rotyob > 360.0) rotyob -= 360.0; } /* ORI: Y */
			
			if (firsty)  firsty=0;
			else { rotxob += .5*(y-oldy); if (rotxob > 360.0) rotxob -= 360.0; } /* ORI: X */
		}
    }
	oldx = x;  
	oldy = y;
	glutPostRedisplay();
}

/******************************************************************************/
/******************************************************************************/

void keyboard (unsigned char key, int x, int y)
{
	
    int mod;
	
	
	switch (key) {
		case 27:   exit(1); 			break;	// ESCAPE
		case 'w':  WIRE = !WIRE;		break;	// wireframe
		case 'r':
			mod = glutGetModifiers();
			if (mod == (GLUT_ACTIVE_ALT)) {
				//glutSolidSphere(0.5,20,20);
				cout << "Entering ioEvents::->  <<" <<endl;
			}
			break;
		case 't': //for translate
			mod = glutGetModifiers();
			if (mod == (GLUT_ACTIVE_ALT)) {
				TORUS = !TORUS;
				cout << "Entering ioSolutions::-> <<" <<endl;
			}
			break;
			
		default: break;   
	}
	
	
	
	glutPostRedisplay();
}

/******************************************************************************/
/******************************************************************************/

void menuOb (int value)
{
	switch (value) {
		case 0:  WIRE = !WIRE;break;
		case 1:  DATAPTS = !DATAPTS; break;
		case 2:  DATATGTS = !DATATGTS; break;
		case 3:  CURVEPTS = !CURVEPTS;  break;
		case 4:  CURVETGTS = !CURVETGTS;break;
		case 5:  CIRCLES =!CIRCLES;break;
		case 6:  CIRCLENORMALS = !CIRCLENORMALS; break;
		case 7:  TUBE = !TUBE;  break; 
		case 8:  TORUS = !TORUS;  break; 
		default: break;
	}
	glutPostRedisplay();
}

/******************************************************************************/
/******************************************************************************/

// void displayOb ()
// {
//   int i,j;
//   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//   glPushMatrix();
//   glTranslatef (transxob, transyob, 0);
//   glScalef  (zoomob, zoomob, zoomob);
//   glRotatef (rotxob, 1.0, 0.0, 0.0);
//   glRotatef (rotyob, 0.0, 1.0, 0.0);
//   glRotatef (rotzob, 0.0, 0.0, 1.0);

//   if (WIRE)
//     {
//       glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
//       glDisable (GL_LIGHTING);
//       glColor3f (0,0,1); // blue
//       glBegin (GL_TRIANGLES);
//       glVertex3dv (tetra[0]); glVertex3dv (tetra[1]); glVertex3dv (tetra[2]);
//       glVertex3dv (tetra[0]); glVertex3dv (tetra[2]); glVertex3dv (tetra[3]);
//       glVertex3dv (tetra[0]); glVertex3dv (tetra[3]); glVertex3dv (tetra[1]);
//       glEnd ();
//       glEnable (GL_LIGHTING);
//     }
//   else
//     {
//       glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
//       glBegin (GL_TRIANGLES);
//       glNormal3f (0,0,-1);
//       glVertex3dv (tetra[0]); glVertex3dv (tetra[1]); glVertex3dv (tetra[2]);
//       glNormal3f (-1,0,0);
//       glVertex3dv (tetra[0]); glVertex3dv (tetra[2]); glVertex3dv (tetra[3]);
//       glNormal3f (0,-1,0);
//       glVertex3dv (tetra[0]); glVertex3dv (tetra[3]); glVertex3dv (tetra[1]);
//       glNormal3f (1/sqrt(3.0),1/sqrt(3.0),1/sqrt(3.0));
//       glVertex3dv (tetra[1]); glVertex3dv (tetra[2]); glVertex3dv (tetra[3]);
//       glEnd ();
//       glEnable (GL_LIGHTING);
//     }

//   glPopMatrix();
//   glutSwapBuffers ();
// }

void  drawPoints()
{
	
	
    glBegin(GL_POINTS);
    for(int i = 0; i < npts; i++)
    {
		glColor3f(0.5,0.0,0.5);
		glVertex3f (MV[0][i],MV[1][i],0);      
		
    }
	glEnd(); 
}

void drawLines(float a,float b,float aa, float bb)
{
	glBegin(GL_LINES);
	glColor3f(0,0.0,0);
	glVertex3f (a ,b, 0);
	glVertex3f (aa ,bb,0);
	glEnd();
	
}



void drawTriangles(int a,int b,int c)
{
    //Check here the way the triangles connect
    glBegin(GL_TRIANGLE_STRIP);
	// glColor3f(0.4f, 0.5f, 0.8f);
	glVertex3f (MV[0][a] ,MV[1][a], 0);
	
	//cout << "*******------********" <<endl;
	//cout << "x: " <<  MV[0][a] << "\t y: "<< MV[1][a]<<endl;
	//glColor3f(0.0f, 1.0f, 0.0f); 
	glVertex3f (MV[0][b] ,MV[1][b], 0);
	
	
	// cout << "x: " <<  MV[0][b] << "\t y: "<< MV[1][b]<<endl;
	//glColor3f(1.0f, 0.35f, 0.45f);  
	glVertex3f (MV[0][c] ,MV[1][c], 0); 
	
	
	// cout << "x: " <<  MV[0][c] << "\t y: "<< MV[1][c]<<endl;
	// cout << "*******------********" <<endl;
	
	glEnd();
	
	glBegin(GL_LINE_LOOP);
	glColor3f(0.8f, 0.1f, 0.1f);
	glVertex3f (MV[0][a] ,MV[1][a], 0);
	
	//cout << "*******------********" <<endl;
	//cout << "x: " <<  MV[0][a] << "\t y: "<< MV[1][a]<<endl;
	//glColor3f(0.0f, 1.0f, 0.0f); 
	glVertex3f (MV[0][b] ,MV[1][b], 0);
	
	
	// cout << "x: " <<  MV[0][b] << "\t y: "<< MV[1][b]<<endl;
	//glColor3f(1.0f, 0.35f, 0.45f);  
	glVertex3f (MV[0][c] ,MV[1][c], 0); 
	
	
	// cout << "x: " <<  MV[0][c] << "\t y: "<< MV[1][c]<<endl;
	// cout << "*******------********" <<endl;
	
	glEnd();
	
}

void Mesh (int* A, int* B, int* C)
{
	int val = 4;
    
	for (int color_ind=0; color_ind<val;color_ind++)
	{ 
		for (int index=color_ind*4; index < (4*color_ind+4); index++)
		{
			float color_chage = color_ind/(float)val*1.0;
			glColor3f(color_chage, 0.45f,(1-color_chage));
			drawTriangles(A[index] ,B[index],C[index]);
		}
		
	}
    
	//drawTriangles(A[0],B[0],C[0]);
	//drawTriangles(A[1],B[1],C[1]);
    
    
}

float centroide (float p1, float p2, float p3)
{
    
    
    float c = 1/3*(p1+p2+p3);
    
    return c;
    
    
}

void drawCentroid(int a,int b,int c)
{
    
    x=_elecslvr_obj.centroide(MV[0][a],MV[0][b],MV[0][c]);
    y=_elecslvr_obj.centroide(MV[1][a],MV[1][b],MV[1][c]);
    
    point a1;
    point m;
    point c1;
    
    a1.x = 2;      a1.y = 0;
    m.x = 0;      m.y = 2;
    c1.x=0.0;     c1.y=0.0;
    
    _elecslvr_obj.ex_p1.x = a1.x;  //Xm
    _elecslvr_obj.ex_p1.y = a1.y;  //Ym
	
    _elecslvr_obj.ex_p2.x = m.x;  //Xa
    _elecslvr_obj.ex_p2.y = m.y;  //Ya
    
    _elecslvr_obj.ex_p3.x = c1.x;  //Xc
    _elecslvr_obj.ex_p3.y = c1.y;  //Yc
    
    float distance1 = 0.0;
    distance1 =_elecslvr_obj.distance_between_vertex(_elecslvr_obj.ex_p1,_elecslvr_obj.ex_p2);
    
    cout << "distance: " << distance1 << endl;
    
	float area = 0.0;
    area =_elecslvr_obj.area_triangle(_elecslvr_obj.ex_p1,_elecslvr_obj.ex_p2,_elecslvr_obj.ex_p3);
    
    cout << "area: " << area << endl;
    
	// x = 1/(float)3 *(MV[0][a]+MV[0][b]+MV[0][c]);
	// y = 1/(float)3 *(MV[1][a]+MV[1][b]+MV[1][c]);
    
    cout << "x: " <<  x << "\t y: "<< y<<endl;
    
    glPointSize(4.0);
    
    glBegin(GL_POINTS);
	glColor3f(0.0f, 1.0f, 0.0f);
	glVertex3f (x ,y, 0);
    glEnd();
    
    glFlush();
    
	
	
	/*  glPointSize(3.0);
	 glColor3f(1.0f, 0.2f, 0.0f);
	 glBegin(GL_POINTS);
	 glVertex2f(5.0, 0.0);
	 glVertex2f(6.0, 1.0);
	 glVertex2f(3.0, 2.0);
	 glEnd();
	 
	 
     /*   glBegin(GL_POINTS);
	 for(int i = 0; i < nptss; i++)
	 {
	 glColor3f(0.5,0.0,0.5);
	 glVertex3f (MV[0][i],MV[1][i],0);      
	 
	 }
	 glEnd();   */
	
	
}

void MeshCentroid (int* A, int* B, int* C)
{
    
    
    for (int index=0; index < npts; index++)
    {
		drawCentroid(A[index] ,B[index],C[index]);
    }
    
	
    
    
}


void  drawTorus()
{
    
	
    
	glMaterialfv(GL_FRONT, GL_AMBIENT, brass_ambient);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, brass_diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR, brass_specular);
	glMaterialf(GL_FRONT, GL_SHININESS, brass_shininess);
	
    glColor3f(0,0.5,0);
    glutSolidTorus(0.275, 0.85, 10, 15); 
	
	//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	//glMatrixMode(GL_MODELVIEW);
	// glPushMatrix();
	// glScalef(1.3, 1.3, 1.3);
	// glRotatef(20.0, 1.0, 0.0, 0.0);
	// glPushMatrix();
	// glTranslatef(-0.65, 0.7, 0.0);
	// glRotatef(90.0, 1.0, 0.0, 0.0);
	//glCallList(TORUS_MATERIAL);
	//glutSolidTorus(0.275, 0.85, 10, 15);
	//glPopMatrix();
	//glPushMatrix();
    
    //material(brass_ambient, brass_diffuse, brass_specular, brass_shininess);
}


void 
material(int dlist,GLfloat * ambient, GLfloat * diffuse,
		 GLfloat * specular, GLfloat shininess)
{
	glNewList(dlist, GL_COMPILE);
	glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
	glMaterialf(GL_FRONT, GL_SHININESS, shininess);
	glEndList();
}

/*
 void drawDataPoints()
 {
 Point3d* pts =  tubeGeom->getDataPts();
 int npts = tubeGeom->getNumDataPts();
 glPointSize(6);
 
 glBegin(GL_POINTS);
 for(int i = 0; i < npts; i++)
 {
 glColor3f(1.0,0.9,0.5);
 glVertex3f (pts[i].x ,pts[i].y, pts[i].z);      
 
 }
 glEnd(); 
 
 }
 
 void drawControlPolygon()
 {
 Spline* spline = tubeGeom->getSpline();
 vector <Bezier*>  bezier = spline->getBezierCurves();
 
 for(int i = 0; i < bezier.size(); i++)
 {
 int numPts =  bezier[i]->getDegree() + 1;
 vector <Point3d> pts  = bezier[i]->getControlPoints();
 glBegin(GL_LINE_STRIP);
 for(int j = 0; j < pts.size();j++)
 {
 glColor3f(1.0,0.0,0.0);
 glVertex3f (pts[j].x ,pts[j].y, pts[j].z);
 // out << pts[j].x  << " " << pts[j].y << " " <<  pts[j].z << endl;
 }
 glEnd();
 }
 }
 
 void drawDataTangents()
 {
 Spline* spline = tubeGeom->getSpline();
 vector<Point3d> dataPts =  spline->getDataPts();
 Point3d* dataTangts =  spline->getDataTangents();
 
 for(int i = 0; i < dataPts.size() -1; i ++)
 {
 glBegin(GL_LINES);
 glColor3f(0.8,1.0,0.75);
 glVertex3f (dataPts[i].x ,dataPts[i].y, dataPts[i].z);
 glVertex3f (dataTangts[i].x + dataPts[i].x ,dataTangts[i].y + dataPts[i].y, 
 dataTangts[i].z + dataPts[i].z);
 glEnd();
 //glVertex3f(dataTangts[i].x , dataTangts[i].y ,dataTangts[i].z );
 }
 
 
 }
 
 void drawSpline()
 {
 Spline* spline = tubeGeom->getSpline();
 vector <Bezier*>  bezier = spline->getBezierCurves();
 // ofstream out("curvePts.txt");
 glPointSize(5);
 for(int i = 0; i < bezier.size(); i++)
 {
 // glBegin(GL_LINE_STRIP);
 int numPts =  bezier[i]->getNumCurvePoints();
 vector <Point3d> pts  = bezier[i]->getCurvePoints();
 //out << "***********" << i << "************" << endl;
 
 glBegin(GL_POINTS);
 for(int j = 0; j < pts.size();j++)
 {
 glColor3f(0.0,0.8,1.0);
 glVertex3f (pts[j].x ,pts[j].y, pts[j].z);
 //out << pts[j].x  << " " << pts[j].y << " " <<  pts[j].z << endl;
 }
 glEnd();
 }
 
 
 
 // out.close();
 }
 
 
 void drawCircles()
 {
 //ofstream out("circle.txt");
 vector<Circle*> circles = tubeGeom->getCircles();
 glPointSize(0.5);
 
 
 for(int i = 0 ; i < circles.size(); i++)
 {
 vector<Point3d> pts = circles[i]->getPts();
 //out << "i "<< i << endl;
 
 glBegin(GL_LINES);
 for(int j = 0; j < pts.size(); j++)
 {
 
 glColor3f(0.4,1.0,0.3);
 glVertex3f (pts[j].x ,pts[j].y, pts[j].z);
 //out << pts[j].x  << " " << pts[j].y << " " <<  pts[j].z << endl;
 }
 glEnd();
 
 }
 //out.close();
 }
 
 
 void drawSampleTangents()
 {
 Spline* spline = tubeGeom->getSpline();
 vector <Bezier*>  bezier = spline->getBezierCurves();
 
 
 //ofstream out("SampleTgts.txt");
 glPointSize(2);
 
 for(int i = 0; i < bezier.size(); i++)
 {
 // glBegin(GL_LINE_STRIP);
 vector <Point3d> pts  = bezier[i]->getTangents();
 //out << "***********" << i << "************" << endl;
 vector<Point3d> curvePts = bezier[i]->getCurvePoints();
 
 for(int j = 0; j < pts.size();j++)
 {
 glBegin(GL_LINES);
 glColor3f(0.0,0.8,1.0);
 glVertex3f (curvePts[j].x , curvePts[j].y, curvePts[j].z);
 glVertex3f (curvePts[j].x + pts[j].x ,curvePts[j].y + pts[j].y, 
 curvePts[j].z + pts[j].z);
 // out << pts[j].x  << " " << pts[j].y << " " <<  pts[j].z << endl;
 glEnd();
 }
 
 }
 
 //out.close();
 }
 
 
 void drawCircleNormals()
 {
 vector<Point3d> pts1;
 vector<Point3d> normal1;
 
 //glLineSize(10);
 vector<Circle*> circles = tubeGeom->getCircles();
 glColor3f(0.2,0.6,0.5);
 
 
 for(int i = 0; i < 1; i++)
 {
 pts1 = circles[i]->getPts();
 normal1 =  circles[i]->getNormal();
 for(int j = 0; j < pts1.size(); j++)
 {
 glBegin(GL_LINES);
 glVertex3f (pts1[j].x ,pts1[j].y, pts1[j].z);
 glVertex3f(pts1[j].x + normal1[j].x, pts1[j].y + normal1[j].y,
 pts1[j].z + normal1[j].z);
 glEnd();
 }
 
 pts1.clear();
 normal1.clear();
 }
 }
 
 void drawTubeWire()
 {
 vector<Point3d> pts1,pts2;
 
 vector<Circle*> circles = tubeGeom->getCircles();
 glColor3f(0.2,0.6,0.9);
 
 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
 glBegin(GL_TRIANGLE_STRIP);
 
 for(int i = 0; i < circles.size() -1 ; i++)
 {
 pts1 = circles[i]->getPts();
 pts2 = circles[i + 1]->getPts();
 //tgts1 = bezier[k]->getTangents();
 //tgts2 = bezier[k + 1]->getTangents();
 
 for(int j = 0; j < pts1.size(); j++)
 {
 glVertex3f (pts1[j].x ,pts1[j].y, pts1[j].z);
 glVertex3f (pts2[j].x ,pts2[j].y, pts2[j].z);
 }
 pts1.clear();
 pts2.clear();
 
 
 }
 glEnd();
 
 }
 
 
 
 void drawTubeSolid()
 {
 vector<Point3d> pts1,pts2;
 vector<Point3d> normal1,normal2;
 
 vector<Circle*> circles = tubeGeom->getCircles();
 glColor3f(0.2,0.6,0.9);
 
 glShadeModel(GL_SMOOTH);
 
 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
 glBegin(GL_TRIANGLE_STRIP);
 
 for(int i = 0; i < circles.size() -1 ; i++)
 {
 pts1 = circles[i]->getPts();
 normal1 =  circles[i]->getNormal();
 pts2 = circles[i + 1]->getPts();
 normal2 =  circles[i + 1]->getNormal();
 
 for(int j = 0; j < pts1.size(); j++)
 {
 glNormal3f(normal1[j].x,normal1[j].y,normal1[j].z);
 glVertex3f (pts1[j].x ,pts1[j].y, pts1[j].z);
 
 glNormal3f(normal2[j].x,normal2[j].y,normal2[j].z); 
 glVertex3f (pts2[j].x ,pts2[j].y, pts2[j].z);
 }
 
 
 pts1.clear();
 pts2.clear();
 
 normal1.clear();
 normal2.clear();
 }
 
 glEnd();
 //glEnable (GL_LIGHTING); 
 }
 */


void displayOb()
{
	int i,j;
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushMatrix();
	glTranslatef (transxob, transyob, 0);
	glScalef  (zoomob, zoomob, zoomob);
	glRotatef (rotxob, 1.0, 0.0, 0.0);
	glRotatef (rotyob, 0.0, 1.0, 0.0);
	glRotatef (rotzob, 0.0, 0.0, 1.0);
	
	glDisable (GL_LIGHTING); 
	if(CIRCLES == 1) MeshCentroid(A,B,C);
	if(DATAPTS == 1)  drawPoints();//drawDataPoints();
	if(DATATGTS == 1) drawLines(0,0,0.5,0.5);
	if(CURVEPTS == 1) Mesh(A,B,C);//drawSpline();
	
	glEnable (GL_LIGHTING);
	if(TORUS == 1) drawTorus();
	
	
	//if(CIRCLES == 1) drawCircles();
	//if(CIRCLENORMALS == 1) drawCircleNormals();
	//if(TUBE == 1 && WIRE == 1) drawTubeWire();
	//if(TUBE == 1 && WIRE == 0) drawTubeSolid();
	
	//display curve
	// drawControlPolygon();
	//drawDataPoints();
	// drawDataTangents();
	// drawSpline();  
	
	
	
	//drawSampleTangents();
	//drawCircles();
	// drawTube();
	glEnable (GL_LIGHTING);
	glPopMatrix();
	glutSwapBuffers ();
}






/******************************************************************************
 ******************************************************************************/

void special (int key, int x, int y)

{
	switch(key)
	{
		case (GLUT_KEY_UP):
			rotxob += 10;
			break;
		case (GLUT_KEY_DOWN):
			rotxob -= 10;
			break;
		case (GLUT_KEY_LEFT):
			rotyob += 10;
			break;
		case (GLUT_KEY_RIGHT):
			rotyob -= 10;
			break;
		default:
			break;
	}
	glutPostRedisplay();
}


void cleanup()
{
	cout << "Entering the clean up code to delete all the objects created : deleting TubeGeom object first \n";
	
	//delete tubeGeom;
	
}

/******************************************************************************
 ******************************************************************************/

int main (int argc, char **argv)
{
	int       ArgsParsed=0;
	RoutineName = argv[ArgsParsed++];
	while (ArgsParsed < argc)
	{
		if ('-' == argv[ArgsParsed][0])
			switch (argv[ArgsParsed++][1])
		{
			case 'x': rotxob = atof(argv[ArgsParsed++]); break;
			case 'y': rotyob = atof(argv[ArgsParsed++]); break;
			case 'z': rotzob = atof(argv[ArgsParsed++]); break;
			case 'l': LAPTOP = 1;                        break;
			case 'h': 
			default : usage(); exit(-1);	             break;
		}
		else ArgsParsed++;
	}
	
	/************************************************************/
	// char* fileName = new char[256];
	// cout << "Enter the file Name \n";
	// cin >> fileName;
	
	// ifstream inp(fileName);
	//tubeGeom = new TubeGeometry(inp);
	
	//-----------------------------------------------------------------------------
    //glutCreateWindow("Pennsylvania Breaker PAB72 SIMULATION");
    
    char* file = (char*) "geo8.mphtxt"; //given file
    IOEVENTS _io_com_obj;
	
    //_io_com_obj.io_read_mpxtxt_files(); //Reading the whole file as a block
	
    _io_com_obj.io_read_mpxtxt_line(file); //Reading a given file
    
    
    
    MV = _io_com_obj.MV; //passing values from comsl to points in opengl
    cout << "MV.x :"<<MV[0][0] << endl;
    cout << "MV.y :"<<MV[1][0] << endl;
    
    A = _io_com_obj.A;
    B = _io_com_obj.B;
    C = _io_com_obj.C;
	
	//-----------------------------------------------------------------------------      
	
	glutInit (&argc, argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	
	int titleht; 	                        // top titlebar
	if (LAPTOP) titleht = 0; else titleht = 20;
	int xleft = 0;
	int xsize=600, ysize=600;
	
	glutInitWindowPosition (xleft,titleht);
	glutInitWindowSize (xsize,ysize);
	char titlebar[100]; 
	strcpy (titlebar, "PAB Simulation Program");
	win = glutCreateWindow (titlebar);
	
	glutDisplayFunc (displayOb);
	glutKeyboardFunc (keyboard);
	glutSpecialFunc (special);
	glutMouseFunc (mouse);
	glutMotionFunc (motionob);
	glutVisibilityFunc (visibility);
	glutReshapeFunc (reshape);
	gfxinit();  
	
	glutCreateMenu (menuOb);
	glutAddMenuEntry ("Shaded/wireframe [w]", 0);
	glutAddMenuEntry ("DataPoints", 1);
	glutAddMenuEntry ("DataTangents", 2);
	glutAddMenuEntry ("SamplePoints", 3);
	glutAddMenuEntry ("SampleTangents", 4);
	glutAddMenuEntry ("Circles", 5);
	glutAddMenuEntry ("CircleNormals", 6);
	glutAddMenuEntry ("Tube", 7);
	glutAttachMenu (GLUT_RIGHT_BUTTON);
	
	atexit(cleanup);
	//inp.close();
	//delete []fileName;
	//delete tubeGeom;
	
	glutMainLoop();
	return 0;
}
